home *** CD-ROM | disk | FTP | other *** search
- (*----------------------------------------------------------------------*)
- (* Emulate_ANSI -- Controls VT100 emulation *)
- (*----------------------------------------------------------------------*)
-
- OVERLAY PROCEDURE Emulate_ANSI( VT100_Allowed : BOOLEAN );
-
- (*----------------------------------------------------------------------*)
- (* *)
- (* Procedure: Emulate_ANSI *)
- (* *)
- (* Purpose: Controls ANSI terminal emulation *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* Emulate_ANSI( VT100_allowed ); *)
- (* *)
- (* VT100_allowed --- TRUE to interpret private DEC sequences *)
- (* *)
- (* Remarks: *)
- (* *)
- (* The ANSI and VT100 emulation are partly based upon TMODEM *)
- (* by Paul Meiners and partly upon ISP100 by Tim Krauskopf. *)
- (* *)
- (* VT100/ANSI commands are interpreted directly by these *)
- (* routines -- the ANSI.SYS driver is not required and should *)
- (* probably not be used, as it will result in an unnecessary *)
- (* performance degradation. *)
- (* *)
- (* This is by no means a complete VT100 or Ansi emulation. It *)
- (* works well enough so that the full-screen editors EDT under *)
- (* VAX/VMS and FSE under CDC/NOS will perform properly. That was *)
- (* my primary intention. You may want to add code to emulate *)
- (* other VT100/VT102/VT103/VT131 features not found here. If you *)
- (* do, please send me back a copy so that I can add your upgrades *)
- (* to future releases of PibTerm. *)
- (* *)
- (* Also note that this emulation assumes 25 lines on the screen. *)
- (* The VT100 only has 24. *)
- (* *)
- (* The following variables are of central interest in the *)
- (* emulation: *)
- (* *)
- (* Escape_Mode --- TRUE if processing escape sequence *)
- (* Escape_Type --- Type of escape sequence being processed *)
- (* Escape_Number --- Number of numeric parameters in escape *)
- (* sequence *)
- (* Escape_Register --- array of numeric parameters in escape *)
- (* sequence *)
- (* Escape_Str --- stores string of escape text; used to *)
- (* gather up a musical score for BBS Ansi. *)
- (* *)
- (*----------------------------------------------------------------------*)
-
- CONST
- ON = TRUE (* Convenient synonym for switches *);
- OFF = FALSE (* Likewise *);
-
- VAR
- Comm_Ch : CHAR (* Character read from comm port *);
- Kbd_Ch : CHAR (* Character read from keyboard *);
- VT100_Graphics_Mode : BOOLEAN (* TRUE if VT100 graphics mode on *);
- VT100_KeyPad : BOOLEAN (* TRUE if alternate keypad in use *);
- Origin_Mode : BOOLEAN (* TRUE for region origin mode *);
- Done : BOOLEAN (* TRUE to stop PIBTERM *);
- B : BOOLEAN (* General purpose flag *);
- Graph_Ch : BYTE (* Graphics character *);
- Itab : BYTE (* Tab stop *);
- Tabcol : BYTE (* Tab column *);
- Curcol : BYTE (* Current column in display *);
- Auto_Print_Mode : BOOLEAN (* IF auto print mode in effect *);
- Printer_Ctrl_Mode : BOOLEAN (* IF printer controller mode on *);
- Print_Line : STRING[80] (* Line to print if print mode on *);
- Reg_Val : INTEGER (* General utility register value *);
-
- Escape_Mode : BOOLEAN (* If processing escape sequence *);
- Escape_Number : INTEGER (* # of numeric parms in esc seq. *);
-
- (* Holds numeric parms in esc seq *)
- Escape_Register : ARRAY[1..50] OF BYTE;
- Escape_Str : AnyStr (* Collects string arg in esc seq *);
- Escape_Type : CHAR (* Type of escape seq. being done *);
-
- (* Remember cursor/attributes *)
- Save_Row_Position : INTEGER;
- Save_Col_Position : INTEGER;
- Save_BG_Color : INTEGER;
- Save_FG_Color : INTEGER;
- Save_Graphics_Mode : BOOLEAN;
- (* Save current scrolling region *)
- Top_Scroll : INTEGER;
- Bottom_Scroll : INTEGER;
-
- Ansi_ForeGround_Color : INTEGER (* Global foreground color here *);
- Ansi_BackGround_Color : INTEGER (* Global background color here *);
- Ansi_Underline_Color : INTEGER (* Color for underlines *);
- Ansi_Bold_Color : INTEGER (* Color for bolding *);
-
- FG : INTEGER (* Foreground color *);
- BG : INTEGER (* Background color *);
-
- Save_Global_FG : INTEGER (* Save global foreground color *);
- Save_Global_BG : INTEGER (* Save global background color *);
- Save_FG : INTEGER (* Save foreground color *);
- Save_BG : INTEGER (* Save background color *);
-
- Double_Width_Mode : BOOLEAN (* Double width characters *);
- Bolding_On : BOOLEAN (* TRUE if bolding on *);
- Blinking_On : BOOLEAN (* TRUE if blinking on *);
-
- CONST (* Special VT100 graphics chars *)
-
- Graphics_Chars: ARRAY[ 95 .. 126 ] Of BYTE
- = ( 32, 4, 177, 9, 12, 13, 10, 248, 241,
- 10, 10, 217, 191, 218, 192, 197, 196, 196,
- 196, 196, 95, 195, 180, 193, 194, 179, 243,
- 242, 227, 168, 156, 250 );
-
- (* VT100 tabs stops *)
- Number_VT100_Tabs = 16;
-
- VT100_Tabs: ARRAY[ 1 .. Number_VT100_Tabs ] OF BYTE
- = ( 9, 17, 25, 33, 41, 49, 57, 65, 73, 74, 75, 76, 77,
- 78, 79, 80 );
-
- Bold_Colors: ARRAY[Black..White] OF BYTE
- = ( DarkGray, LightBlue, LightGreen, LightCyan,
- LightRed, LightMagenta, Yellow, White,
- DarkGray, LightBlue, LightGreen, LightCyan,
- LightRed, LightMagenta, Yellow, White );
-
- Normal_Colors: ARRAY[Black..White] OF BYTE
- = ( Black, Blue, Green, Cyan,
- Red, Magenta, Brown, LightGray,
- Black, Blue, Green, Cyan,
- Red, Magenta, Brown, LightGray );
-
- (* ------------------------------------------------------------------------ *)
- (* PibPlaySet --- Set up to play music *)
- (* PibPlay --- Play Music through Speaker *)
- (* ------------------------------------------------------------------------ *)
-
- PROCEDURE PibPlaySet;
-
- (* ------------------------------------------------------------------------ *)
- (* *)
- (* Procedure: PibPlaySet *)
- (* *)
- (* Purpose: Sets up to play music though PC's speaker *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* PibPlaySet; *)
- (* *)
- (* Calls: None *)
- (* *)
- (* ------------------------------------------------------------------------ *)
-
- BEGIN (* PibPlaySet *)
-
- (* Default Octave *)
- Note_Octave := 4;
- (* Default sustain is semi-legato *)
- Note_Fraction := 0.875;
- (* Note is quarter note by default *)
- Note_Length := 0.25;
- (* Moderato pace by default *)
- Note_Quarter := 500.0;
-
- END (* PibPlaySet *);
-
- PROCEDURE PibPlay( S : AnyStr );
-
- (* ------------------------------------------------------------------------ *)
- (* *)
- (* Procedure: PibPlay *)
- (* *)
- (* Purpose: Play music though PC's speaker *)
- (* *)
- (* Calling Sequence: *)
- (* *)
- (* PibPlay( Music_String : AnyStr ); *)
- (* *)
- (* Music_String --- The string containing the encoded music to be *)
- (* played. The format is the same as that of the *)
- (* MicroSoft Basic PLAY Statement. The string *)
- (* must be <= 254 characters in length. *)
- (* *)
- (* Calls: Sound *)
- (* GetInt (Internal) *)
- (* *)
- (* Remarks: The characters accepted by this routine are: *)
- (* *)
- (* A - G Musical Notes *)
- (* # or + Following A - G note, indicates sharp *)
- (* - Following A - G note, indicates flat *)
- (* < Move down one octave *)
- (* > Move up one octave *)
- (* . Dot previous note (extend note duration by 3/2) *)
- (* MN Normal duration (7/8 of interval between notes) *)
- (* MS Staccato duration *)
- (* ML Legato duration *)
- (* Ln Length of note (n=1-64; 1=whole note, *)
- (* 4=quarter note, etc.) *)
- (* Pn Pause length (same n values as Ln above) *)
- (* Tn Tempo, n=notes/minute (n=32-255, default n=120) *)
- (* On Octave number (n=0-6, default n=4) *)
- (* Nn Play note number n (n=0-84) *)
- (* *)
- (* The following two commands are IGNORED by PibPlay: *)
- (* *)
- (* MF Complete note before continuing *)
- (* MB Another process may begin before speaker is *)
- (* finished playing note *)
- (* *)
- (* IMPORTANT --- PibPlaySet MUST have been called at least once before *)
- (* this routine is called. *)
- (* *)
- (* ------------------------------------------------------------------------ *)
-
- CONST
- (* Offsets in octave of natural notes *)
-
- Note_Offset : ARRAY[ 'A'..'G' ] OF INTEGER
- = ( 9, 11, 0, 2, 4, 5, 7 );
-
- (* Frequencies for 7 octaves *)
-
- Note_Freqs: ARRAY[ 0 .. 84 ] OF INTEGER
- =
- (*
- C C# D D# E F F# G G# A A# B
- *)
- ( 0,
- 65, 69, 73, 78, 82, 87, 92, 98, 104, 110, 116, 123,
- 131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
- 262, 278, 294, 312, 330, 350, 370, 392, 416, 440, 466, 494,
- 524, 556, 588, 624, 660, 700, 740, 784, 832, 880, 932, 988,
- 1048, 1112, 1176, 1248, 1320, 1400, 1480, 1568, 1664, 1760, 1864, 1976,
- 2096, 2224, 2352, 2496, 2640, 2800, 2960, 3136, 3328, 3520, 3728, 3952,
- 4192, 4448, 4704, 4992, 5280, 5600, 5920, 6272, 6656, 7040, 7456, 7904 );
-
- Quarter_Note = 0.25; (* Length of a quarter note *)
-
-
- VAR
- (* Frequency of note to be played *)
- Play_Freq : INTEGER;
-
- (* Duration to sound note *)
- Play_Duration : INTEGER;
-
- (* Duration of rest after a note *)
- Rest_Duration : INTEGER;
-
- (* Offset in Music string *)
- I : INTEGER;
- (* Current character in music string *)
- C : CHAR;
- (* Note Frequencies *)
-
- Freq : ARRAY[ 0 .. 6 , 0 .. 11 ] OF INTEGER ABSOLUTE Note_Freqs;
-
- N : INTEGER;
- XN : REAL;
- K : INTEGER;
-
- (* ------------------------------------------------------------------------ *)
-
- FUNCTION GetInt : INTEGER;
-
- (* --- Get integer from music string --- *)
-
- VAR
- N : INTEGER;
-
- BEGIN (* GetInt *)
-
- N := 0;
-
- WHILE( S[I] In ['0'..'9'] ) DO
- BEGIN
- N := N * 10 + ORD( S[I] ) - ORD('0');
- I := I + 1;
- END;
-
- I := I - 1;
-
- GetInt := N;
-
- END (* GetInt *);
-
- (* ------------------------------------------------------------------------ *)
-
- BEGIN (* PibPlay *)
- (* Append blank to end of music string *)
- S := S + ' ';
- (* Point to first character in music *)
- I := 1;
- (* BEGIN loop over music string *)
- WHILE( I < LENGTH( S ) ) DO
-
- BEGIN (* Interpret Music *)
- (* Get next character in music string *)
- C := UpCase(S[I]);
- (* Interpret it *)
- CASE C OF
-
- 'A'..'G' : BEGIN (* A Note *)
-
- N := Note_Offset[ C ];
-
- Play_Freq := Freq[ Note_Octave , N ];
-
- XN := Note_Quarter * ( Note_Length / Quarter_Note );
-
- Play_Duration := TRUNC( XN * Note_Fraction );
-
- Rest_Duration := TRUNC( XN * ( 1.0 - Note_Fraction ) );
-
- (* Check for sharp/flat *)
-
- IF S[I+1] In ['#','+','-' ] THEN
- BEGIN
-
- I := I + 1;
-
- CASE S[I] OF
- '#' : Play_Freq :=
- Freq[ Note_Octave , N + 1 ];
- '+' : Play_Freq :=
- Freq[ Note_Octave , N + 1 ];
- '-' : Play_Freq :=
- Freq[ Note_Octave , N - 1 ];
- ELSE ;
- END (* Case *);
-
- END;
-
- (* Check for note length *)
-
- IF S[I+1] In ['0'..'9'] THEN
- BEGIN
-
- I := I + 1;
- N := GetInt;
- XN := ( 1.0 / N ) / Quarter_Note;
-
- Play_Duration :=
- TRUNC( Note_Fraction * Note_Quarter * XN );
-
- Rest_Duration :=
- TRUNC( ( 1.0 - Note_Fraction ) *
- Xn * Note_Quarter );
-
- END;
- (* Check for dotting *)
-
- IF S[I+1] = '.' THEN
- BEGIN
-
- XN := 1.0;
-
- WHILE( S[I+1] = '.' ) DO
- BEGIN
- XN := XN * 1.5;
- I := I + 1;
- END;
-
- Play_Duration :=
- TRUNC( Play_Duration * XN );
-
- END;
-
- (* Play the note *)
-
- Sound( Play_Freq );
- Delay( Play_Duration );
- NoSound;
- Delay( Rest_Duration );
-
- END (* A Note *);
-
- 'M' : BEGIN (* 'M' Commands *)
-
- I := I + 1;
- C := S[I];
-
- Case C Of
-
- 'F' : ;
- 'B' : ;
- 'N' : Note_Fraction := 0.875;
- 'L' : Note_Fraction := 1.000;
- 'S' : Note_Fraction := 0.750;
- ELSE ;
-
- END (* Case *);
-
-
- END (* 'M' Commands *);
-
- 'O' : BEGIN (* Set Octave *)
-
- I := I + 1;
- N := ORD( S[I] ) - ORD('0');
-
- IF ( N < 0 ) OR ( N > 6 ) THEN N := 4;
-
- Note_Octave := N;
-
- END (* Set Octave *);
-
- '<' : BEGIN (* Drop an octave *)
-
- IF Note_Octave > 0 THEN
- Note_Octave := Note_Octave - 1;
-
- END (* Drop an octave *);
-
- '>' : BEGIN (* Ascend an octave *)
-
- IF Note_Octave < 6 THEN
- Note_Octave := Note_Octave + 1;
-
- END (* Ascend an octave *);
-
- 'N' : BEGIN (* Play Note N *)
-
- I := I + 1;
-
- N := GetInt;
-
- IF ( N > 0 ) AND ( N <= 84 ) THEN
- BEGIN
-
- Play_Freq := Note_Freqs[ N ];
-
- XN := Note_Quarter *
- ( Note_Length / Quarter_Note );
-
- Play_Duration := TRUNC( XN * Note_Fraction );
-
- Rest_Duration := TRUNC( XN * ( 1.0 - Note_Fraction ) );
-
- END
-
- ELSE IF ( N = 0 ) THEN
- BEGIN
-
- Play_Freq := 0;
- Play_Duration := 0;
- Rest_Duration :=
- TRUNC( Note_Fraction * Note_Quarter *
- ( Note_Length / Quarter_Note ) );
-
- END;
-
- Sound( Play_Freq );
- Delay( Play_Duration );
- NoSound;
- Delay( Rest_Duration );
-
- END (* Play Note N *);
-
- 'L' : BEGIN (* Set Length of Notes *)
-
- I := I + 1;
- N := GetInt;
-
- IF N > 0 THEN Note_Length := 1.0 / N;
-
- END (* Set Length of Notes *);
-
- 'T' : BEGIN (* # of quarter notes in a minute *)
-
- I := I + 1;
- N := GetInt;
-
- Note_Quarter := ( 1092.0 / 18.2 / N ) * 1000.0;
-
- END (* # of quarter notes in a minute *);
-
- 'P' : BEGIN (* Pause *)
-
- I := I + 1;
- N := GetInt;
-
- IF ( N < 1 ) THEN N := 1
- ELSE IF ( N > 64 ) THEN N := 64;
-
- Play_Freq := 0;
- Play_Duration := 0;
- Rest_Duration :=
- TRUNC( ( ( 1.0 / N ) / Quarter_Note )
- * Note_Quarter );
-
- Sound( Play_Freq );
- Delay( Play_Duration );
- NoSound;
- Delay( Rest_Duration );
-
- END (* Pause *);
-
- ELSE
- (* Ignore other stuff *);
-
- END (* Case *);
-
- I := I + 1;
-
- END (* Interpret Music *);
-
- (* Make sure sound turned off when through *)
- NoSound;
-
- END (* PibPlay *);
-